# src/app.py
from flask import request, jsonify, Flask, render_template
import pandas as pd
from src.predict import TalentAttritionPredict
from src.web_controller import WebController
import json
import os

app = Flask(__name__)
app.secret_key = 'talent_attrition_prediction_secret_key'

# 配置模板和静态文件夹路径（使用绝对路径）
current_dir = os.path.dirname(os.path.abspath(__file__))
template_dir = os.path.join(os.path.dirname(current_dir), 'templates')
static_dir = os.path.join(os.path.dirname(current_dir), 'static')

# 确保模板文件夹存在
if os.path.exists(template_dir):
    app.template_folder = template_dir
else:
    print(f"警告: 模板文件夹不存在: {template_dir}")

if os.path.exists(static_dir):
    app.static_folder = static_dir
else:
    print(f"警告: 静态文件夹不存在: {static_dir}")

# 全局预测器实例，避免每次请求都重新加载模型
predictor = None

# 创建Web控制器实例
web_controller = WebController()

def get_predictor():
    global predictor
    if predictor is None:
        predictor = TalentAttritionPredict()
    return predictor

# 添加欢迎页面路由
@app.route('/', methods=['GET'])
def welcome():
    """Web界面主页"""
    try:
        return web_controller.get_index_page()
    except Exception as e:
        print(f"渲染主页时出错: {e}")
        # 如果模板不存在，返回简单的HTML页面
        return """
        <!DOCTYPE html>
        <html>
        <head>
            <title>人才流失预测系统</title>
            <meta charset="utf-8">
        </head>
        <body>
            <h1>人才流失预测系统</h1>
            <p>系统正在初始化中，请稍后...</p>
            <p><a href="/health">检查系统状态</a></p>
        </body>
        </html>
        """, 200

# API预测接口
@app.route('/api/predict', methods=['POST'])
def predict():
    try:
        # 获取请求数据
        data = None

        # 方式1: 从JSON请求体获取
        if request.is_json:
            try:
                data = request.get_json()
            except Exception as e:
                app.logger.error(f"JSON解析错误: {str(e)}")

        # 方式2: 从表单数据获取
        if data is None and request.form:
            try:
                data = request.form.to_dict()
                # 尝试转换数值类型
                for key in data:
                    try:
                        if key in ['Age', 'DistanceFromHome', 'Education', 'EmployeeNumber',
                                   'EnvironmentSatisfaction', 'JobInvolvement', 'JobLevel',
                                   'JobSatisfaction', 'MonthlyIncome', 'NumCompaniesWorked',
                                   'PercentSalaryHike', 'PerformanceRating', 'RelationshipSatisfaction',
                                   'StockOptionLevel', 'TotalWorkingYears', 'TrainingTimesLastYear',
                                   'WorkLifeBalance', 'YearsAtCompany', 'YearsInCurrentRole',
                                   'YearsSinceLastPromotion', 'YearsWithCurrManager']:
                            data[key] = int(data[key])
                    except:
                        pass
            except Exception as e:
                app.logger.error(f"表单数据解析错误: {str(e)}")

        # 方式3: 从原始请求数据获取
        if data is None:
            try:
                raw_data = request.get_data(as_text=True)
                if raw_data:
                    data = json.loads(raw_data)
            except Exception as e:
                app.logger.error(f"原始数据解析错误: {str(e)}")

        # 如果仍然没有获取到数据，返回错误
        if data is None:
            return jsonify({
                "error": "无法解析请求数据",
                "supported_formats": [
                    "JSON请求体: {'Age': 30, 'BusinessTravel': 'Travel_Rarely', ...}",
                    "表单数据: Age=30&BusinessTravel=Travel_Rarely&..."
                ]
            }), 400

        # 获取预测器实例
        predictor_instance = get_predictor()

        # 将输入数据转换为DataFrame格式
        input_data = pd.DataFrame([data])

        # 执行特征工程
        processed_data = predictor_instance.feature_engineering(input_data)

        # 进行预测
        prediction_proba = predictor_instance.model.predict_proba(processed_data)[:, 1]
        prediction = (prediction_proba >= predictor_instance.threshold).astype(int)

        # 返回预测结果
        result = {
            "prediction": int(prediction[0]),
            "probability": float(prediction_proba[0]),
            "threshold": float(predictor_instance.threshold),
            "message": "员工流失风险高" if prediction[0] == 1 else "员工流失风险低"
        }

        return jsonify(result), 200

    except Exception as e:
        app.logger.error(f"预测过程中发生错误: {str(e)}")
        return jsonify({
            "error": f"预测过程中发生错误: {str(e)}",
            "建议": "请检查输入数据格式是否正确"
        }), 500

# Web表单预测接口
@app.route('/predict', methods=['POST'])
def web_predict():
    """Web表单预测接口"""
    try:
        form_data = request.form.to_dict()
        result, status_code = web_controller.predict_from_form(form_data)
        if status_code == 200:
            # 检查模板是否存在
            if os.path.exists(os.path.join(app.template_folder, 'result.html')):
                return render_template('result.html', result=result)
            else:
                # 如果模板不存在，返回简单的HTML结果
                return f"""
                <!DOCTYPE html>
                <html>
                <head>
                    <title>预测结果</title>
                    <meta charset="utf-8">
                </head>
                <body>
                    <h1>预测结果</h1>
                    <p>预测: {result.get('prediction', 'N/A')}</p>
                    <p>概率: {result.get('probability', 'N/A')}</p>
                    <p>消息: {result.get('message', 'N/A')}</p>
                    <a href="/">返回首页</a>
                </body>
                </html>
                """, 200
        else:
            # 检查错误模板是否存在
            if os.path.exists(os.path.join(app.template_folder, 'error.html')):
                return render_template('error.html', error=result.get('error', '未知错误'))
            else:
                # 如果模板不存在，返回简单的错误页面
                return f"""
                <!DOCTYPE html>
                <html>
                <head>
                    <title>错误</title>
                    <meta charset="utf-8">
                </head>
                <body>
                    <h1>发生错误</h1>
                    <p>错误信息: {result.get('error', '未知错误')}</p>
                    <a href="/">返回首页</a>
                </body>
                </html>
                """, 500
    except Exception as e:
        error_msg = f"预测过程中发生错误: {str(e)}"
        if os.path.exists(os.path.join(app.template_folder, 'error.html')):
            return render_template('error.html', error=error_msg)
        else:
            return f"""
            <!DOCTYPE html>
            <html>
            <head>
                <title>错误</title>
                <meta charset="utf-8">
            </head>
            <body>
                <h1>发生错误</h1>
                <p>错误信息: {error_msg}</p>
                <a href="/">返回首页</a>
            </body>
            </html>
            """, 500

# 添加健康检查接口
@app.route('/health', methods=['GET'])
def health_check():
    """
    健康检查接口
    """
    try:
        # 尝试加载预测器
        predictor_instance = get_predictor()
        status = "healthy" if predictor_instance else "unhealthy"
    except Exception as e:
        status = "unhealthy"
        print(f"健康检查失败: {e}")

    return jsonify({
        "status": status,
        "service": "talent-attrition-prediction-service",
        "timestamp": pd.Timestamp.now().isoformat()
    }), 200

# 添加示例数据接口
@app.route('/example', methods=['GET'])
def example_data():
    """
    提供示例数据格式
    """
    example = {
        "Age": 30,
        "BusinessTravel": "Travel_Rarely",
        "Department": "Research & Development",
        "DistanceFromHome": 10,
        "Education": 3,
        "EducationField": "Life Sciences",
        "EmployeeNumber": 1234,
        "EnvironmentSatisfaction": 3,
        "Gender": "Male",
        "JobInvolvement": 3,
        "JobLevel": 2,
        "JobRole": "Research Scientist",
        "JobSatisfaction": 4,
        "MaritalStatus": "Married",
        "MonthlyIncome": 5000,
        "NumCompaniesWorked": 1,
        "OverTime": "No",
        "PercentSalaryHike": 13,
        "PerformanceRating": 3,
        "RelationshipSatisfaction": 4,
        "StockOptionLevel": 1,
        "TotalWorkingYears": 5,
        "TrainingTimesLastYear": 3,
        "WorkLifeBalance": 3,
        "YearsAtCompany": 3,
        "YearsInCurrentRole": 2,
        "YearsSinceLastPromotion": 1,
        "YearsWithCurrManager": 1
    }

    return jsonify({
        "message": "示例数据格式",
        "example_data": example
    }), 200

# API文档接口
@app.route('/api/docs', methods=['GET'])
def api_documentation():
    """API文档"""
    try:
        return jsonify(web_controller.get_api_documentation())
    except Exception as e:
        return jsonify({"error": f"获取API文档失败: {str(e)}"}), 500

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=9001, debug=False)
